#include "smUpdate.h"

#include "core_cm3.h"

#include "smFlash.h"
#include "stdio.h"
#include "stm32f10x_can.h"
#include "string.h"
#include "sys.h"

SysParam_t sysRunCfg = {0}; /* 上电是空的 等待初始化 */
ulong *pId = &(sysRunCfg.rfId);
pFunction Jump_To_Application;
uint32_t JumpAddress;

/* bootloader中默认 是升级的 */
SysParam_t SystemParamDefault = {.hardwareVersion = 0x00000001,
                                 .app0_Version = 0x00000000,
                                 .app0_Status = APP_NORMAL,
                                 .app1_Version = 0x00000000,
                                 .app1_Status = APP_ERROR,
                                 .devType = runApp0};

void crcInit(void) {
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
  CRC_ResetDR();

  SystemParamReadCheck(&sysRunCfg); /* 检查参数 */
  mApp.isProcBleData = bFalse;
#if 0
  if (sysRunCfg.devType != runApp0) {
    sysRunCfg.devType = runApp0; /* 运行状态 */

    updatfg2flash();
    SystemParamReadCheck(&sysRunCfg);
  }
#endif

  mApp.sysParam = &sysRunCfg;
	mApp.isUpdataOk = bTrue;
}

void SystemParamReadCheck(SysParam_t *pData) {
  uint32_t crcdatalen = 0;
  SysParam_t sysParam, sysParamBackup;
  uint32_t paramCrc = 0;
  do {
    /* 读主参数区数据 */
    STMFLASH_Read(configure, (u16 *)&sysParam, (sizeof(sysParam)) / 2);
    /* 读取备份区数据 */
    STMFLASH_Read(configureBack, (u16 *)&sysParamBackup,
                  (sizeof(sysParamBackup)) / 2);

    crcdatalen = (sizeof(sysParam)) / 4 - sizeof(uint32_t) / 4;

    /* 校验主参数区 */
    CRC_ResetDR();
    paramCrc = CRC_CalcBlockCRC((uint32_t *)&sysParam, crcdatalen);

    if (paramCrc == sysParam.SystemParamCRC) {
      /* 读取参数成功 */

      /* 校验备份区参数 */
      CRC_ResetDR();
      paramCrc = CRC_CalcBlockCRC((uint32_t *)&sysParamBackup, crcdatalen);

      if (paramCrc == sysParamBackup.SystemParamCRC) {
        /* 读取参数成功, 判断数据是否一致 */
        if (0 != memcmp(&sysParam, &sysParamBackup, sizeof(sysParam))) {
          /* 写入备份区 */
          STMFLASH_Write(configureBack, (u16 *)&sysParamBackup,
                         (sizeof(sysParam)) / 2);
        }
        /* 相同参数不处理 */
        break;
      }
      /* 备份校验失败 */
      memcpy(&sysParamBackup, &sysParam, sizeof(sysParamBackup));
      STMFLASH_Write(configureBack, (u16 *)&sysParamBackup,
                     (sizeof(sysParam)) / 2);
      break;
    }
    /* 主分区校验失败，校验备份分区 */
    CRC_ResetDR();
    paramCrc = CRC_CalcBlockCRC((uint32_t *)&sysParamBackup, crcdatalen);
    if (paramCrc == sysParamBackup.SystemParamCRC) {
      /* 读取参数成功 */

      /* 备份区参数写入主参数区 */
      memcpy(&sysParam, &sysParamBackup, sizeof(sysParamBackup));
      STMFLASH_Write(configure, (u16 *)&sysParam, (sizeof(sysParam)) / 2);
      break;
    }

    /* 备份分区也没有参数时，写入默认参数 */
    GetChipID(SystemParamDefault.macInfo.chipId);      /* cpu id */
    cpuChipType(&SystemParamDefault.macInfo.chipType); /* cpu 类型 */
    /* 厂家要求的机型 这里随便默认一个 */

    /* 配置蓝牙通信波特率 115200 */
    SystemParamDefault.macInfo.bleInfo.bleBaund = defaultBleBaund;
    /* 配置蓝牙名称 */
    sprintf((char *)SystemParamDefault.macInfo.bleInfo.bleName, "%s",
            defBleName);

    CRC_ResetDR();
    SystemParamDefault.SystemParamCRC =
        CRC_CalcBlockCRC((uint32_t *)&SystemParamDefault, crcdatalen);
    memcpy(&sysParam, &SystemParamDefault, sizeof(sysParamBackup));
    memcpy(&sysParamBackup, &SystemParamDefault, sizeof(sysParamBackup));
    /* 更新参数 */
    STMFLASH_Write(configure, (u16 *)&sysParam, (sizeof(sysParam)) / 2);
    STMFLASH_Write(configureBack, (u16 *)&sysParamBackup,
                   (sizeof(sysParam)) / 2);

  } while (0);

  /* 参数加载给 sysRunCfg */
  memcpy(&sysRunCfg, &sysParam, sizeof(sysRunCfg));
  memcpy((void *)&(mApp.macInfo), (void *)&(sysRunCfg.macInfo),
         sizeof(mApp.macInfo));
}

void updatfg2flash(void) {
  uint32_t crcdatalen = 0;
  /* crc */
  crcdatalen = (sizeof(sysRunCfg)) / 4 - sizeof(uint32_t) / 4;
  CRC_ResetDR();
  sysRunCfg.SystemParamCRC =
      CRC_CalcBlockCRC((uint32_t *)&sysRunCfg, crcdatalen);

  /* 更新参数 */
  STMFLASH_Write(configure, (u16 *)&sysRunCfg, (sizeof(sysRunCfg)) / 2);
  STMFLASH_Write(configureBack, (u16 *)&sysRunCfg, (sizeof(sysRunCfg)) / 2);
}

static void disAbleIrq(void) {
  __set_FAULTMASK(1);
  /* 关闭嘀嗒定时器 */
  SysTick->CTRL = 0x00;  //禁用SYSTICK中断
  SysTick->LOAD = 0;     //每1/configTICK_RATE_HZ秒中断一次
  SysTick->CTRL = 0;     //禁用SYSTICK

  /* 关闭crc时钟 */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, DISABLE);
  /* 锁上flash */
  FLASH_Lock();
  /* 关闭串口 */
  USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); /* 使能串口接受中断 */
  USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);  //空闲中断
  USART_Cmd(USART1, DISABLE);
  USART_DeInit(USART1);
  USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); /* 使能串口接受中断 */
  USART_ITConfig(USART2, USART_IT_IDLE, DISABLE);  //空闲中断
  USART_Cmd(USART2, DISABLE);
  USART_DeInit(USART2);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, DISABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                             RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
                             RCC_APB2Periph_GPIOE,
                         DISABLE);

  GPIO_DeInit(GPIOA);
  GPIO_DeInit(GPIOB);
  GPIO_DeInit(GPIOC);
  GPIO_DeInit(GPIOD);
  GPIO_DeInit(GPIOE);

  /* timer */
  TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
  TIM_Cmd(TIM4, DISABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE);

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);
  DMA_Cmd(DMA1_Channel1, DISABLE);
  RCC_DeInit();
  WWDG_DeInit();
  USART_DeInit(USART1);
  USART_DeInit(USART2);
  TIM_DeInit(TIM4);
  DMA_DeInit(DMA1_Channel1);
  //  ADC_DeInit(ADC1);
  __disable_irq();
}

void go2Boot(void) {
  if (((*(__IO unsigned int *)bootLoaderAddr) & 0x2FFE0000) == 0x20000000) {
    disAbleIrq();
    JumpAddress = *(__IO uint32_t *)(bootLoaderAddr + 4);
    Jump_To_Application = (pFunction)JumpAddress;
    __set_PSP(*(__IO uint32_t *)bootLoaderAddr);
    __set_CONTROL(0);
    __set_MSP(*(__IO uint32_t *)bootLoaderAddr);
    Jump_To_Application();
  }
}
